package com.couchbase.loadgen; import java.io.IOException; import java.io.StringWriter; import java.util.HashMap; import java.util.Iterator; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import org.codehaus.jackson.impl.DefaultPrettyPrinter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Config { private static Config config = null; private static final Logger LOG = LoggerFactory.getLogger(Config.class); private static final String PROPERTIES_JSON_ID = "properties"; public static final String CHURN_DELTA = "churndelta"; public static final String DB = "db"; public static final String DO_TRANSACTIONS = "dotransactions"; public static final String EXPORTER = "exporter"; public static final String EXPORT_FILE = "exportfile"; public static final String INSERT_COUNT = "insertcount"; public static final String INSERT_ORDER = "insertorder"; public static final String INSERT_START = "insertstart"; public static final String KEY_PREFIX = "keyprefix"; public static final String LABEL = "label"; public static final String MEASUREMENT_TYPE = "measurementtype"; public static final String MEMCACHED_ADDRESS = "memcached.address"; public static final String MEMCACHED_PORT = "memcached.port"; public static final String MEMADD = "memaddproportion"; public static final String MEMAPPEND = "memappendproportion"; public static final String MEMCAS = "memcasproportion"; public static final String MEMDECR = "memdecrproportion"; public static final String MEMDELETE = "memdeleteproportion"; public static final String MEMGET = "memgetproportion"; public static final String MEMGETS = "memgetsproportion"; public static final String MEMINCR = "memincrproporiton"; public static final String MEMPREPEND = "memprependproportion"; public static final String MEMREPLACE = "memreplaceproportion"; public static final String MEMSET = "memsetproportion"; public static final String MEMUPDATE = "memupdateproportion"; public static final String OP_COUNT = "operationcount"; public static final String PROTOCOL = "protocol"; public static final String PRINT_STATS_INTERVAL = "printstatsinterval"; public static final String RECORD_COUNT = "recordcount"; public static final String REQUEST_DISTRIBUTION = "requestdistribution"; public static final String TARGET = "target"; public static final String THREAD_COUNT = "threadcount"; public static final String VALUE_LENGTH = "valuelength"; public static final String WORKING_SET = "workingset"; public static final String WORKLOAD = "workload"; private HashMap<String, Object> properties; private Config() { properties = new HashMap<String, Object>(); properties.put(CHURN_DELTA, new Integer(1)); properties.put(DB, new String()); properties.put(DO_TRANSACTIONS, new Boolean(true)); properties.put(EXPORTER, "com.couchbase.loadgen.measurements.exporter.TextMeasurementsExporter"); properties.put(EXPORT_FILE, new String()); properties.put(INSERT_ORDER, "hashed"); properties.put(INSERT_START, new Integer(0)); properties.put(KEY_PREFIX, "user"); properties.put(LABEL, ""); properties.put(MEASUREMENT_TYPE, "histogram"); properties.put(MEMCACHED_ADDRESS, "10.2.1.15"); properties.put(MEMCACHED_PORT, new Integer(11211)); properties.put(MEMADD, new Double(0.0)); properties.put(MEMAPPEND, new Double(0.0)); properties.put(MEMCAS, new Double(0.0)); properties.put(MEMDECR, new Double(0.0)); properties.put(MEMDELETE, new Double(0.0)); properties.put(MEMGET, new Double(1.0)); properties.put(MEMGETS, new Double(0.0)); properties.put(MEMINCR, new Double(0.0)); properties.put(MEMPREPEND, new Double(0.0)); properties.put(MEMREPLACE, new Double(0.0)); properties.put(MEMSET, new Double(0.0)); properties.put(MEMUPDATE, new Double(0.0)); properties.put(OP_COUNT, new Integer(10000)); properties.put(PRINT_STATS_INTERVAL, new Integer(5)); properties.put(PROTOCOL, "ascii"); properties.put(RECORD_COUNT, new Integer(10000)); properties.put(REQUEST_DISTRIBUTION, "zipfian"); properties.put(TARGET, new Integer(5000)); properties.put(THREAD_COUNT, new Integer(1)); properties.put(WORKING_SET, new Integer(5)); properties.put(VALUE_LENGTH, new Integer(256)); } public static Config getConfig() { if (config == null) return (config = new Config()); return config; } public void setConfig(String configjson) { JsonFactory factory = new JsonFactory(); try { JsonParser p = factory.createJsonParser(configjson.getBytes()); p.nextToken(); p.nextToken(); if (p.getCurrentName().equals(PROPERTIES_JSON_ID)) { p.nextToken(); while(p.nextToken() != JsonToken.END_OBJECT) { String key = p.getCurrentName(); JsonToken token = p.nextToken(); if (token == JsonToken.VALUE_NUMBER_INT && properties.get(key) instanceof Integer) { properties.put(key, new Integer(p.getIntValue())); } else if (token == JsonToken.VALUE_NUMBER_FLOAT && properties.get(key) instanceof Double) { properties.put(key, new Double(p.getDoubleValue())); } else if ((token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE) && properties.get(key) instanceof Boolean) { properties.put(key, new Boolean(p.getBooleanValue())); } else if (token == JsonToken.VALUE_STRING && properties.get(key) instanceof String){ properties.put(key, p.getText()); } else { LOG.error("Field for " + key + " did not match type"); } } } else { LOG.error("Attempted to set an invalid config"); } } catch (JsonParseException e) { LOG.error("Attempted to set an invalid config"); } catch (IOException e) { LOG.error("Attempted to set an invalid config"); } } public boolean set(String key, String value) { if (!properties.containsKey(key)) return false; if (properties.get(key) instanceof String) properties.put(key, value); else if (properties.get(key) instanceof Boolean) properties.put(key, new Boolean(value)); else if (properties.get(key) instanceof Integer) properties.put(key, new Integer(value)); else if (properties.get(key) instanceof Double) properties.put(key, new Double(value)); return true; } public Object get(String key) { return properties.get(key); } public String getPropertyJson(String key) { if (properties.containsKey(key)) { JsonStringBuilder builder = new JsonStringBuilder(); builder.startJsonString(); try { Object value = properties.get(key); System.out.println(key + " " + value); if (value instanceof String) builder.addElement(key, (String) value); else if (value instanceof Boolean) builder.addElement(key, ((Boolean) value)); else if (value instanceof Integer) builder.addElement(key, ((Integer) value)); else if (value instanceof Double) builder.addElement(key, ((Double) value)); builder.endJson(); } catch (JsonGenerationException e) { return null; } catch (IOException e) { return null; } System.out.println(builder.toString()); return builder.toString(); } return null; } public String getConfigJson() { StringWriter sw = new StringWriter(); JsonFactory factory = new JsonFactory(); JsonGenerator g; try { g = factory.createJsonGenerator(sw); g.setPrettyPrinter(new DefaultPrettyPrinter()); g.writeStartObject(); g.writeFieldName(PROPERTIES_JSON_ID); g.writeStartObject(); // TODO: Can I sort this Iterator<String> itr = properties.keySet().iterator(); String key; Object value; while (itr.hasNext()) { key = itr.next(); value = properties.get(key); if (value instanceof String) g.writeStringField(key, (String) value); else if (value instanceof Boolean) g.writeBooleanField(key, ((Boolean) value).booleanValue()); else if (value instanceof Integer) g.writeNumberField(key, ((Integer) value).intValue()); else if (value instanceof Double) g.writeNumberField(key, ((Double) value).doubleValue()); } g.writeEndObject(); g.writeEndObject(); g.close(); } catch (JsonGenerationException e) { return null; } catch (IOException e) { return null; } return sw.toString(); } }